# 加载ui文件
import sys
from PyQt5 import QtWidgets, uic, QtGui, QtCore
from functools import partial
import os
import cv2 as cv
import numpy as np


class MainWindow:
    def __init__(self):
        # 加载文件
        self.ui = uic.loadUi("./ui/image_show.ui")

        # 相关数值可视化
        self.ui.brightness_slider.valueChanged.connect(
            partial(self.slider_change, "brightness")
        )
        self.ui.gamma_slider.valueChanged.connect(partial(self.slider_change, "gamma"))
        self.brightness, self.gamma = 0, 1
        # 图片加载模块
        self.ui.image_src.returnPressed.connect(self.load_image_by_path)
        self.ui.load_btn.clicked.connect(self.load_image_by_path)

        self.src_image = None
        self.image = None
        self.base_zoom_step = 0.2
        self.rate = 1

        # 放大缩小按钮
        self.ui.zoom_in_btn.clicked.connect(partial(self.zoom, 1))  # 放大
        self.ui.zoom_out_btn.clicked.connect(partial(self.zoom, -1))  # 缩小

    def zoom(self, rate):
        # 放大缩小图片
        self.rate += rate * self.base_zoom_step
        self.rate = min(max(self.rate, 0.1), 4)
        self.ui.zoom_value.setText(f"{self.rate:.2f}")
        # 图像缩放
        if self.src_image is None:
            self.msg_error("请先加载图片")
            return
        self.update_image(self.brightness, self.gamma)

    def slider_change(self, name):
        # 在合适的位置上显示滑动条数值
        if name == "brightness":
            self.brightness = self.ui.brightness_slider.value()
            self.ui.brightness_value.setText(str(self.brightness))
        elif name == "gamma":
            self.gamma = self.ui.gamma_slider.value() / 10
            self.ui.gamma_value.setText(f"{self.gamma:.2f}")
        else:
            pass
        self.update_image(int(self.brightness), float(self.gamma))

    def load_image_by_path(self):
        # 加载图片
        self.image_path = os.path.join(self.ui.image_src.text())
        # 对路径进行处理
        self.image_path = self.image_path.strip('"').replace("\\", "/")
        if not os.path.exists(self.image_path):
            # 提示错误信息
            self.msg_error(f"图片路径错误, 图片不存在\n{self.image_path}")
        else:
            # 加载图片
            self.src_image = cv.imread(self.image_path, cv.IMREAD_ANYCOLOR)
            self.show_image(self.src_image,self.src_image)

    def update_image(self, brightness: int, gamma: float):
        # 直接通过pixmap显示图片，在图像动态处理中会用到
        # 不可能两个参数同时更新
        if self.src_image is None:
            self.msg_error("请先加载图片")
            return
        self.image = self.src_image.copy()
        self.image = cv.resize(
            self.src_image,
            (
                int(self.src_image.shape[1] * self.rate),
                int(self.src_image.shape[0] * self.rate),
            ),
        )
        resizeImage = self.image.copy()
        if brightness is not None:
            # 调整亮度
            self.image = np.clip(
                self.image.astype(np.int16) + brightness, 0, 255
            ).astype(np.uint8)
        if gamma is not None:
            # 调整伽马
            self.image = cv.pow(self.image / 255.0, gamma) * 255
            self.image = self.image.astype(np.uint8)

        self.show_image(resizeImage,self.image)

    def show_image(self, src_image,dst_image):
        # 显示原始图片
        src_scene = QtWidgets.QGraphicsScene()
        height, width, channel = src_image.shape
        bytesPerLine = 3 * width
        qImg = QtGui.QImage(
            src_image.data, width, height, bytesPerLine, QtGui.QImage.Format_RGB888
        ).rgbSwapped()
        pixmap = QtGui.QPixmap.fromImage(qImg)
        src_scene.addPixmap(pixmap)
        self.ui.src_image_view.setScene(src_scene)

        # 显示图片处理后的图片
        dst_scene = QtWidgets.QGraphicsScene()
        height, width, channel = dst_image.shape
        bytesPerLine = 3 * width
        qImg = QtGui.QImage(
            dst_image.data, width, height, bytesPerLine, QtGui.QImage.Format_RGB888
        ).rgbSwapped()
        pixmap = QtGui.QPixmap.fromImage(qImg)
        dst_scene.addPixmap(pixmap)
        self.ui.image_view.setScene(dst_scene)

    def msg_error(self, msg):
        # 弹出错误提示
        QtWidgets.QMessageBox.critical(self.ui, "错误", msg)

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    # 增加窗口图标
    app.setWindowIcon(QtGui.QIcon("./ui/icon.jpg"))
    window = MainWindow()
    window.ui.show()
    sys.exit(app.exec_())
